/**
 * 成员管理弹层-Code业务封装
 */

import React from 'react';
import PropTypes from 'prop-types';
import { Message, Button, Balloon, ConfigProvider } from '@teamix/ui';
import MemberList from '@alife/yunxiao-member-panel';
import { YunxiaoIcon } from '@alife/devops-ui';
import Member from '@alife/yunxiao-member';
import { ENUM, ORGANIZATION_ADMIN_ROLES, PROJECT_ADMIN_ROLES } from 'utils/constants.js';
import exceed from 'utils/apimap';
import { navigate, navigateHref } from 'utils/router';
import { getFeature } from 'utils/features';
import utils from 'utils';
import PathEllipsis from 'components/pathEllipsis';
import track from 'utils/track';
import { customMemberSearchAll } from 'api';
import intl from '../../locale';

const codeUserId = Number(window.FORCE.user.codeUserId);
const tbUserId = window.FORCE.user.id;
const { organization_id } = window.FORCE.organization;

export default class CodeMemberList extends React.Component {
  static propTypes = {
    trigger: PropTypes.element,
    // 传递类型: project/group
    pathResourceType: PropTypes.string,
    pathResourceId: PropTypes.number,
    title: PropTypes.string,
    onChange: PropTypes.func,
    onAddMembers: PropTypes.func,
    role: PropTypes.string.isRequired,
    onClose: PropTypes.func,
    // 是否是管理员（列表有成员管理权限的都是管理员）
    isAdmin: PropTypes.bool,
    // 顶级路径ID（列表无pathResource，传入 库用namespace_id 组用parent_id）
    parentId: PropTypes.number,
    // 在mini版中点击邀请成员为true，自动弹窗添加弹窗
    autoOpenAddPanel: PropTypes.bool,
    onRemoveMembers: PropTypes.func,
  };

  static defaultProps = {
    trigger: null,
    pathResourceType: 'project',
    pathResourceId: null,
    title: null,
    onChange: null,
    onAddMembers: null,
    onClose: () => {},
    isAdmin: false,
    parentId: null,
    autoOpenAddPanel: false,
  };

  constructor(props) {
    super(props);
    this.state = {
      members: [],
      // isLoading: true,
      visible: props.visible || false,
      // manageRoleIds自己可以操作下拉调整权限，其他user用disabled控制
      customRoles: [
        {
          label: intl.get({
            id: 'code-assets.src.utils.locale.Visitors',
            defaultMessage: '浏览者',
          }),
          value: ENUM.access_level_id.REPORTER,
          manageRoleIds: [20],
        },

        {
          label: intl.get({
            id: 'code-assets.src.utils.locale.Developers',
            defaultMessage: '开发者',
          }),
          value: ENUM.access_level_id.DEVELOPER,
          manageRoleIds: [20, 30],
        },

        {
          label: intl.get({
            id: 'code-assets.src.utils.locale.Administrator',
            defaultMessage: '管理员',
          }),
          value: ENUM.access_level_id.MASTER,
          manageRoleIds: [20, 30, 40],
        },
      ],

      // 企业成员
      orgMembers: [],
      memberVisible: false,
    };
  }

  componentDidMount() {
    this.initMemberList();
    // this.getProjectMembers();
    this.getOrgMembers();
  }

  initMemberList = () => {
    const { pathResourceId, pathResourceType } = this.props;
    if (!pathResourceId) return;
    const isProject = pathResourceType === 'project';
    const getMembers = exceed.forceFetch({
      api: `members.${pathResourceType}.get`,
      params: { [isProject ? 'projectId' : 'groupId']: pathResourceId },
    });

    const getTeams = exceed.fetch({
      api: 'api.teams',
      data: {
        onlyFirstLevel: false,
        pageSize: 1000,
      },
    });

    Promise.all([getMembers, getTeams]).then(([members, teams]) => {
      const teamsRes = teams.result.result;
      this.teamsRes = teamsRes;
      this.getProjectMembers(members.list, teamsRes);
    });
  };

  onOpenInviteUrl = (page) => {
    if (page === 'invite') {
      track({
        action: 'click-add-member',
        page: 'codeup-member',
        type: '',
        control: '',
      });
    } else if (page === 'moreInvite') {
      track({
        action: 'click-add-member',
        page: 'codeup-invite-member',
        type: '',
        control: '',
      });
    }
  };

  getOrgMembers = (cb) => {
    exceed
      .forceFetch({
        api: 'organization.member',
        params: {
          orgId: organization_id,
        },
      })
      .then((result) => {
        this.setState({
          orgMembers: result.result || [],
        });

        cb && cb();
      })
      .catch((err) => {
        console.log(err);
      });
  };

  formatterList = (list, teamData) => {
    list.map((item) => {
      if (item.member_type === 'USERS') {
        item.memberType = 'user';
      } else if (item.member_type === 'TEAMS') {
        item.memberType = 'team';
        const team = teamData.filter((v) => v._id === item.tb_user_id);
        if (team.length) {
          item.name = team[0].name;
          item.teamObj = team[0];
          item._id = item.tb_user_id;
        }
      }
      item._userId = item.tb_user_id || item.extern_uid;
      item.access_level = item.access_level >= 40 ? 40 : item.access_level;
      item.roleId = item.access_level;
      item.avatarUrl = item.avatar_url || '';
      if (item.inherited) {
        const { path_with_namespace, name_with_namespace } = item.inherited;
        const text = utils.getGroupPath(name_with_namespace);
        item.extra = (
          <div className="member-list-extra-info">
            <div className="member-list-extra-info-left">
              {intl.get({
                id: 'code-assets.components.memberList.member.PermissionsAreInheritedFrom',
                defaultMessage: '权限继承自：',
              })}
            </div>
            <div className="member-list-extra-info-right">
              {/* <Title trigger={<a href={`/${path_with_namespace}`} onClick={(e) => { this.goParent(e, path_with_namespace); }}>{text}</a>} align="t">
                 <div>{text}</div>
               </Title> */}
              <a
                className="member-inherited-path"
                onClick={(e) => {
                  this.goParent(e, path_with_namespace);
                }}
              >
                <PathEllipsis path={text} />
              </a>
            </div>
          </div>
        );
      } else if (item.related_infos && item.related_infos.length) {
        const related_ids = item.related_infos.map((v) => v.related_id);
        const team = teamData.filter((v) => related_ids.includes(v._id));
        if (!item.parent || !item.parent.name) {
          item.parent = {
            name: team.map((v) => v.name).join('，'),
          };
        }
        if (item.extra) {
          return item;
        }
        item.extra = (
          <div className="member-list-extra-info">
            <div className="member-list-extra-info-left">
              {intl.get({
                id: 'code-assets.components.memberList.member.MembersBelong',
                defaultMessage: '成员隶属于：',
              })}
            </div>
            <div className="member-list-extra-info-right">
              {team && team.length && team.map((v) => v.name).join('，')}
            </div>
          </div>
        );
      }

      return item;
    });
    return list;
  };

  getProjectMembers = (listData, teamData) => {
    if (!teamData) {
      exceed
        .fetch({
          api: 'api.teams',
          data: {
            onlyFirstLevel: false,
            pageSize: 1000,
          },
        })
        .then((res) => {
          const teamDataRes = res.result.result || [];
          this.getProjectMembers(listData, teamDataRes);
        });
      return;
    }
    if (listData) {
      const list = this.formatterList(listData, teamData);
      this.setState({ members: list });
      return;
    }
    // 根据传入的参数决定是组成员列表还是库成员列表
    const { pathResourceId, pathResourceType } = this.props;
    const isProject = pathResourceType === 'project';
    exceed
      .forceFetch({
        api: `members.${pathResourceType}.get`,
        params: { [isProject ? 'projectId' : 'groupId']: pathResourceId },
      })
      .then((result) => {
        const { list } = result;
        const fList = this.formatterList(list, teamData);
        this.setState({ members: fList });
      });
  };

  goParent = (e, path) => {
    e.preventDefault();
    navigate(`/${path}`, { state: { forceUpdate: true } });
    this.props.onClose();
  };

  putProjectMembers = (user) => {
    const userId = user.id;
    const access_level = user.roleId;
    const { member_type, related_infos = [] } = user;
    const { pathResourceId, pathResourceType } = this.props;
    const isProject = pathResourceType === 'project';

    return new Promise((resolve) => {
      exceed
        .forceFetch({
          api: `membersV4.${pathResourceType}.put`,
          params: { [isProject ? 'projectId' : 'groupId']: pathResourceId, userId },
          data: {
            access_level,
            member_type,
            related_infos:
              related_infos &&
              related_infos.map((v) => ({
                ...v,
                member_type: 'TEAMS',
              })),
          },
        })
        .then(() => {
          Message.success({
            title: intl.get({
              id: 'code-assets.components.memberList.member.MemberPermissionsUpdated',
              defaultMessage: '成员权限更新成功',
            }),
          });

          this.getProjectMembers();
          resolve();
        });
    });
  };

  postProjectMembers = (users, access_level) => {
    const { pathResourceId, pathResourceType } = this.props;
    const isProject = pathResourceType === 'project';
    const userList = users
      .filter((v) => !!v._userId)
      .map((v) => ({
        extern_uid: v._userId,
        member_type: 'USERS',
      }));

    const teamList = users
      .filter((v) => !v._userId)
      .map((v) => ({
        extern_uid: v._id,
        member_type: 'TEAMS',
      }));

    let teamUsers = [];
    users
      .filter((v) => !v._userId)
      .forEach((item) => {
        teamUsers = teamUsers.concat(
          item.members.map((v) => ({
            extern_uid: v._userId,
            member_type: 'USERS',
            related_id: item._id,
          })),
        );
      });
    exceed
      .forceFetch({
        api: `membersV4.${pathResourceType}.post`,
        params: { [isProject ? 'projectId' : 'groupId']: pathResourceId },
        data: {
          member_info_list: [...userList, ...teamList, ...teamUsers],
          access_level,
          // expire_at,
        },
      })
      .then(() => {
        Message.success({
          title: intl.get({
            id: 'code-assets.components.memberList.member.AddedSuccessfully',
            defaultMessage: '添加成功',
          }),
        });

        this.getProjectMembers();
      });
  };

  deleteProjectMembers = (user, remove_type) => {
    const userId = user.id || user._userId;
    const { pathResourceId, pathResourceType } = this.props;
    const isProject = pathResourceType === 'project';
    const isExit = userId === codeUserId;
    let fetchParams;
    if (isProject) {
      const { member_type, extern_uid } = user;
      fetchParams = {
        api: 'members.project.delete.post',
        params: { projectId: pathResourceId, userId },
        data: {
          extern_uid: extern_uid || user._userId,
          member_type,
          remove_type,
        },
      };
    } else if (isExit) {
      // 退出组
      fetchParams = {
        api: 'members.group.leave',
        params: { groupId: pathResourceId },
      };
    } else {
      const { member_type, extern_uid } = user;
      fetchParams = {
        api: 'members.group.delete.post',
        params: { groupId: pathResourceId, userId },
        data: {
          extern_uid: extern_uid || user._userId,
          member_type,
          remove_type,
        },
      };
    }
    exceed.forceFetch(fetchParams).then(() => {
      Message.success({
        title: isExit
          ? intl.get({
              id: 'code-assets.components.memberList.member.ExitSucceeded',
              defaultMessage: '退出成功',
            })
          : intl.get({
              id: 'code-assets.components.memberList.member.RemovedSuccessfully',
              defaultMessage: '移除成功',
            }),
      });

      if (isExit) {
        navigateHref('/');
      } else {
        this.getProjectMembers();
      }
    });
  };

  onChangeMember = (user) => {
    // 更改权限
    return this.putProjectMembers(user);
  };

  onAddMembers = (users, role) => {
    if (!users.length) {
      Message.error({
        title: intl.get({
          id: 'code-assets.components.memberList.member.SelectAtLeastOneMember',
          defaultMessage: '请至少选择一名成员',
        }),
      });
    }
    this.setState({
      memberVisible: false,
    });

    this.postProjectMembers(users, role);
  };

  onRemoveMembers = (users, remove_type) => {
    // 删除成员
    let type;
    if (remove_type === 'teamAndMember') {
      type = 'REMOVE_ALL';
    } else if (remove_type === 'team') {
      type = 'ONLY_REMOVE_TEAM';
    }
    users && this.deleteProjectMembers(users, type);
  };

  onVisibleChange = (visible) => {
    this.setState({
      visible,
    });
  };

  onMemberClose = () => {
    this.setState({
      memberVisible: false,
    });

    if (this.state.orgMembers.length === 1) {
      this.getOrgMembers();
    }
  };

  loaderTeamAndMember = (member) =>
    new Promise((resolve) => {
      exceed
        .fetch({
          api: 'uiless-get-memberAndteams',
          data: { onlyFirstLevel: true },
          params: { id: member._userId },
        })
        .then((res) => {
          let memberList = [];
          let teamList = [];
          if (res && res.result) {
            if (res.result.members && res.result.members.result) {
              memberList = res.result.members.result;
            }
            if (res.result.teams && res.result.teams.result) {
              teamList = res.result.teams.result;
            }
          }
          const { members } = this.state;
          memberList = memberList.map((v) => {
            const memberInfo = members.find((i) => v._userId === i._userId);
            return {
              ...v,
              ...memberInfo,
              member_type: 'USERS',
              memberType: 'user',
            };
          });
          teamList = teamList.map((v) => ({
            ...v,
            roleId: member.roleId,
            member_type: 'TEAMS',
            memberType: 'team',
            _userId: v._id,
          }));

          resolve({
            memberList: this.formatterList(memberList, [member]),
            teamList,
          });
        });
    });

  render() {
    const {
      title,
      onChange,
      onAddMembers,
      onRemoveMembers,
      role,
      pathResourceType,
      isAdmin,
      parentId,
      ...others
    } = this.props;
    const { members, visible, customRoles, orgMembers, memberVisible } = this.state;

    // 企业管理员不在库内也要操作
    const orgRole = (window.FORCE.organization && window.FORCE.organization.user_role) || '';
    const isOrgAdmin = orgRole ? ORGANIZATION_ADMIN_ROLES.includes(orgRole) : false;

    // 最后一个管理员禁止修改
    const adminMembers = members.filter((item) => {
      return item.roleId >= ENUM.access_level_id.MASTER;
    });
    // 是不是顶级路径
    const { pathResource, organization } = window.FORCE;
    const isRoot =
      (parentId || Number(pathResource.parentId)) === Number(organization.namespace_id);

    // 禁止添加成员 (企业管理员则为开启，非企业管理员需具体判断 -> 不是管理员都不能添加)
    const addMembersDisabled =
      !isOrgAdmin && !(isAdmin || PROJECT_ADMIN_ROLES.includes(pathResource.role));

    members.forEach((item) => {
      if (item.inherited) {
        // 继承成员不可修改
        item.disabled = true;
      } else if (item._userId === tbUserId) {
        // 自己展示下拉
        item.disabled = false;
      } else {
        // 管理员均可修改其他，非管理员禁止
        item.disabled = addMembersDisabled;
      }

      // 顶级路径最后一个管理员禁用
      if (item.roleId >= ENUM.access_level_id.MASTER) {
        if (adminMembers.length === 1 && isRoot) {
          item.displayRoleName = (
            <Balloon.Tooltip
              trigger={
                <span>
                  {intl.get({
                    id: 'code-assets.components.memberList.member.Administrator',
                    defaultMessage: '管理员',
                  })}
                </span>
              }
              align="t"
            >
              {intl.get({
                id: 'code-assets.components.memberList.member.CannotBeChangedOrExited',
                defaultMessage: '不可更改或退出，顶级路径至少需要一个管理员',
              })}
            </Balloon.Tooltip>
          );

          item.disabled = true;
        } else if (item.inherited) {
          item.disabled = true;
        } else {
          item.disabled = false;
        }
      }
    });

    const addMembersTrigger = (
      <Button
        type="primary"
        disabled={addMembersDisabled}
        text
        style={{ marginLeft: 16 }}
        onClick={() => {
          if (addMembersDisabled) {
            return;
          }
          this.setState({
            memberVisible: true,
          });
        }}
      >
        <YunxiaoIcon type="add-fill" />
        {intl.get({
          id: 'code-assets.components.memberList.member.AddMembers',
          defaultMessage: '添加成员',
        })}
      </Button>
    );

    const curMembers = members.filter((item) => {
      if (item.member_type === 'USERS') {
        if (!item.inherited) {
          return true;
        } else if (item.sync_by_current_source) {
          return true;
        }
        return false;
      } else {
        return !item.inherited;
      }
    });

    // 临时方案，等底座后端邀请链接重构后即可去掉
    const nextUrl = encodeURIComponent(`${location.origin}?org_id=${organization_id}`);
    const inviteUrl = `https://devops.aliyun.com/org-admin/${organization_id}/members/member?invite=true&next_url=${nextUrl}`;
    // console.log(inviteUrl, 'inviteUrl')

    return (
      <React.Fragment>
        <ConfigProvider prefix="yx-">
          <MemberList
            // 界面样式type
            // type="mini"
            title={
              <span id="lfs-list-member-list">
                {title ||
                  intl.get({
                    id: 'code-assets.components.memberList.member.MemberManagement',
                    defaultMessage: '成员管理',
                  })}
              </span>
            }
            dataSource={members}
            onVisibleChange={this.onVisibleChange}
            shouldUpdatePosition
            maxContentHeight={420}
            visible={visible}
            customRoles={customRoles}
            currentUserId={tbUserId}
            onAdd={onAddMembers || this.onAddMembers}
            onRemove={onRemoveMembers || this.onRemoveMembers}
            onChangeItem={this.onChangeMember}
            isAdmin={isOrgAdmin}
            inviteBanner={orgMembers.length === 1}
            track={track}
            inviteBannerClick={() => {
              this.setState({
                memberVisible: true,
              });
            }}
            listLoader={async (m) => {
              const { teamList = [], memberList = [] } = (await this.loaderTeamAndMember(m)) || {};
              return [...teamList, ...memberList];
            }}
            extra={addMembersTrigger}
            needSearchAll={getFeature('member.needSearchAll')}
            {...others}
          />
        </ConfigProvider>

        <ConfigProvider prefix="yx-">
          <Member
            overlayProps={{ container: 'lfs-list-member-list' }}
            visible={memberVisible}
            multiple
            autoFocus
            onChange={this.onAddMembers}
            customRoles={customRoles}
            align="tr br"
            mode="add"
            value={curMembers}
            isAdmin={isOrgAdmin}
            inviteUrl={inviteUrl}
            // 企业只有自己的时候传  否则不传或传'home'
            defaultPage={orgMembers.length === 1 ? 'moreInvite' : 'home'}
            onRequestClose={this.onMemberClose}
            onInviteBack={this.getOrgMembers}
            onOpenInviteUrl={this.onOpenInviteUrl}
            extraMemberTypes={getFeature('member.memberList.extraMemberTypes')}
            customSearchAll={getFeature('member.customSearchAll') ? customMemberSearchAll : undefined}
          />
        </ConfigProvider>
      </React.Fragment>
    );
  }
}
